home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / dump / RCS / main.c,v < prev   
Text File  |  1992-03-28  |  60KB  |  2,767 lines

  1. head     1.12;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.12
  10. date     92.03.28.17.29.31;  author kupfer;  state Exp;
  11. branches ;
  12. next     1.11;
  13.  
  14. 1.11
  15. date     92.03.28.11.54.54;  author jhh;  state Exp;
  16. branches ;
  17. next     1.10;
  18.  
  19. 1.10
  20. date     91.11.22.15.02.14;  author jhh;  state Exp;
  21. branches ;
  22. next     1.9;
  23.  
  24. 1.9
  25. date     91.11.22.14.09.03;  author jhh;  state Exp;
  26. branches ;
  27. next     1.8;
  28.  
  29. 1.8
  30. date     91.10.11.11.57.18;  author jhh;  state Exp;
  31. branches ;
  32. next     1.7;
  33.  
  34. 1.7
  35. date     91.09.10.11.16.59;  author jhh;  state Exp;
  36. branches ;
  37. next     1.6;
  38.  
  39. 1.6
  40. date     91.06.28.12.27.23;  author shirriff;  state Exp;
  41. branches ;
  42. next     1.5;
  43.  
  44. 1.5
  45. date     91.06.05.15.06.58;  author mgbaker;  state Exp;
  46. branches ;
  47. next     1.4;
  48.  
  49. 1.4
  50. date     91.05.10.17.00.37;  author mgbaker;  state Exp;
  51. branches ;
  52. next     1.3;
  53.  
  54. 1.3
  55. date     90.11.15.01.21.03;  author rab;  state Exp;
  56. branches ;
  57. next     1.2;
  58.  
  59. 1.2
  60. date     90.10.07.15.10.39;  author rab;  state Exp;
  61. branches ;
  62. next     1.1;
  63.  
  64. 1.1
  65. date     90.09.07.11.47.34;  author rab;  state Exp;
  66. branches ;
  67. next     ;
  68.  
  69.  
  70. desc
  71. @@
  72.  
  73.  
  74. 1.12
  75. log
  76. @Use -L flag so that tar will save long names.  Lint.
  77. @
  78. text
  79. @/*
  80.  * main.c --
  81.  *
  82.  *      Main routine for the sprite dump program.
  83.  *
  84.  *
  85.  * Copyright 1988 Regents of the University of California
  86.  * Permission to use, copy, modify, and distribute this
  87.  * software and its documentation for any purpose and without
  88.  * fee is hereby granted, provided that the above copyright
  89.  * notice appear in all copies.  The University of California
  90.  * makes no representations about the suitability of this
  91.  * software for any purpose.  It is provided "as is" without
  92.  * express or implied warranty.
  93.  */
  94.  
  95. #ifndef lint
  96. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.11 92/03/28 11:54:54 jhh Exp Locker: kupfer $";
  97. #endif
  98.  
  99. #include <sprite.h>
  100. #include <stdio.h>
  101. #include <stdlib.h>
  102. #include <string.h>
  103. #include <ctype.h>
  104. #include <fcntl.h>
  105. #include <signal.h>
  106. #include <time.h>
  107. #include <pwd.h>
  108. #include <unistd.h>
  109. #include <sys/types.h>
  110. #include <sys/stat.h>
  111. #include <sys/wait.h>
  112. #include <sys/param.h>
  113. #include <sys/dir.h>
  114. #include <option.h>
  115. #include <fs.h>
  116. #include <dev/tape.h>
  117. #include <status.h>
  118. #include <cfuncproto.h>
  119. #include <varargs.h>
  120. #include <assert.h>
  121. #include <dev/exabyte.h>
  122. #include <bstring.h>
  123. #include <sys/errno.h>
  124.  
  125. #define DEBUG
  126.  
  127. #ifdef DEBUG
  128. #define debugp(x) ((void) fprintf x, fflush(stderr))
  129. #else
  130. #define debugp(x)
  131. #endif
  132.  
  133. #define SPRITE_OLD_DUMP_HEADER "SPRITE DUMP TAPE #"
  134. #define SPRITE_DUMP_HEADER     "SPRITE DUMP TAPE,"
  135. #define SPRITE_DUMP_INFO    " Version %d Level %d Tape %d"
  136. #define SPRITE_DUMP_VERSION    1
  137.  
  138. #define DUMPDATES                  "/sprite/admin/dump/dumpdates"
  139. #define LOGFILE                 "/sprite/admin/dump/dumplog"
  140. #define DRIVELOG        "/sprite/admin/dump/statuslog"
  141. #define TAR                   "tar.gnu"
  142.  
  143. #define KBytes(n)    (n * 1024)
  144. #define MBytes(n)    (1024 * KBytes(n))
  145.  
  146. #define    IOBUF_SIZE    KBytes(62)    /* Exebyte likes 62KB chunks */
  147.  
  148. #define TOC_SIZE_OLD     MBytes(10)    /* TOC occupied 10 MB on the tape */
  149. #define    TOC_USEABLE_OLD    MBytes(2)    /* About 2 MB of it can be used */
  150.  
  151. #define TOC_SIZE     KBytes(16)    /* No longer needs to be big. */
  152. #define    TOC_USEABLE    TOC_SIZE    /* and we can use it all */
  153.  
  154. #define TAR_BLOCK_SIZE    KBytes(64)    /* Do the tar in 64K blocks. */
  155.  
  156. #define LABEL_SIZE_OLD    IOBUF_SIZE    /* Size of useable label. */
  157. #define LABEL_SIZE    TOC_SIZE    /* Size of useable label. */
  158.  
  159. static char tapeBuffer[IOBUF_SIZE];
  160. static char *directoryToDump;
  161. static tarChild;
  162. static int pipefd[2];
  163. static int archivefd;
  164. static int dumpLevel = 0;
  165. static int tapeNumber;
  166. static int tapeLevel;
  167. static int fileNumber;
  168. static int verbose;
  169. static char *archiveFileName;
  170. static char *mailWho;
  171. static time_t lastTime;
  172. static time_t startTime;
  173. static int fatalErrors;
  174. static int nonFatalErrors;
  175. static int archiveFileIsATapeDrive;
  176. static int printTOC;
  177. static int progArgc;
  178. static char **progArgv;
  179. static int reInitialize = 0;
  180. static int reInitializeSafe = 0;
  181. static long totalBytes;
  182. static int debug;
  183. static int oldFormat;
  184. static int tarBlocks;
  185. static int tapePosition = 0;
  186. static int version = 0;
  187. static int labelSize = 0;
  188. static int lastFile;
  189. static int official = 1;
  190. #ifdef PROG_RESTORE
  191. static int printContents = 0;
  192. #endif
  193.  
  194. #ifdef PROG_DUMP
  195. static int resetAccessTimes;
  196.  
  197. static Option OptionArray[] = {
  198.   { OPT_TRUE,   "a", (char *) &resetAccessTimes, "Reset access times"        },
  199.   { OPT_TRUE,   "d", (char *) &debug,            "Debug"                     },
  200.   { OPT_STRING, "f", (char *) &archiveFileName,  "Name of archive file"      },
  201.   { OPT_INT,    "i", (char *) &tapeNumber,       "Initialize the tape"       },
  202.   { OPT_INT,    "l", (char *) &dumpLevel,        "Dump level (0-9)"          },
  203.   { OPT_STRING, "m", (char *) &mailWho,          "Send mail upon completion" },
  204.   { OPT_TRUE,   "r", (char *) &reInitialize,     "Re-initialize the tape"    },
  205.   { OPT_TRUE,   "s", (char *) &reInitializeSafe, "Safely re-initialize tape" },
  206.   { OPT_TRUE,   "t", (char *) &printTOC,         "Print table of contents"   },
  207.   { OPT_TRUE,   "v", (char *) &verbose,          "Verbose"                   },
  208.   { OPT_FALSE,   "u", (char *) &official,           "Unofficial dump"           },
  209. };
  210. #endif
  211.  
  212. #ifdef PROG_RESTORE
  213. static int relativePaths;
  214. static Option OptionArray[] = {
  215.   { OPT_STRING, "f", (char *) &archiveFileName,  "Name of archive"           },
  216.   { OPT_TRUE,   "d", (char *) &debug,            "Debug"                     },
  217.   { OPT_INT,    "n", (char *) &fileNumber,       "File number to use"        },
  218.   { OPT_TRUE,   "r", (char *) &relativePaths,    "Use relative pathnames"    },
  219.   { OPT_TRUE,   "t", (char *) &printTOC,         "Print table of contents"   },
  220.   { OPT_TRUE,   "v", (char *) &verbose,          "Verbose"                   },
  221.   { OPT_TRUE,   "T", (char *) &printContents,    "Print contents of dump file"},
  222. };
  223. #endif
  224.  
  225. static void cleanup_sighup _ARGS_((int sig));
  226. static void cleanup_sigint _ARGS_((int sig));
  227. static void cleanup_sigquit _ARGS_((int sig));
  228. static void cleanup_sigpipe _ARGS_((int sig));
  229. static void cleanup_sigterm _ARGS_((int sig));
  230.  
  231. static void openArchiveFile _ARGS_((void));
  232. static void forkOffTar _ARGS_((void));
  233. static void dumpDirectory _ARGS_((char *dir));
  234. static void initializeTape _ARGS_((void));
  235. static void sendMail _ARGS_((const char *msg));
  236. static void rewindTape _ARGS_((void));
  237. static void fatal _ARGS_((char *fmt, ...));
  238. static void warning _ARGS_((char *fmt, ...));
  239. static void readTapeLabel _ARGS_((void));
  240. static void rewindTape _ARGS_((void));
  241. static void openLog _ARGS_((void));
  242. static void skipOverFiles _ARGS_((void));
  243. #ifdef PROG_RESTORE
  244. static void findLastFile _ARGS_((void));
  245. #endif
  246. static void waitForChildToDie _ARGS_((void));
  247. static void setFileNumber _ARGS_((void));
  248. static void quote_string _ARGS_((char *to, const char *from));
  249. static void checkTape _ARGS_((void));
  250. static int parseDumpInfo _ARGS_((char *buf));
  251. static void gotoEOD _ARGS_((void));
  252. static ReturnStatus skipFiles _ARGS_((int num));
  253.  
  254. #ifdef PROG_DUMP
  255. static int  getNextDumpDateEntry _ARGS_((void));
  256. static void writeTapeLabel _ARGS_((void));
  257. static void flushOutput _ARGS_((void));
  258. static void getDumpDate _ARGS_((void));
  259. static void recordTime _ARGS_((void));
  260. #endif
  261.  
  262. #ifdef __STDC__
  263. #define VOID void
  264. #endif
  265.  
  266. void
  267. main(argc, argv)
  268.     int argc;
  269.     char **argv;
  270. {
  271.     uid_t    root;
  272.     uid_t    dumper;
  273.     struct passwd    *pwPtr;
  274.     uid_t    euid;
  275.     extern    uid_t    geteuid();
  276.     extern    int    setreuid();
  277. #ifdef PROG_DUMP
  278.     ReturnStatus    status;
  279. #endif
  280.     char         *date;
  281.     int            i;
  282.  
  283.  
  284.     signal(SIGHUP, cleanup_sighup);
  285.     signal(SIGINT, cleanup_sigint);
  286.     signal(SIGQUIT, cleanup_sigquit);
  287.     signal(SIGPIPE, cleanup_sigpipe);
  288.     signal(SIGTERM, cleanup_sigterm);
  289.     startTime = time(0L);
  290.     date = asctime(localtime(&startTime));
  291.     date[24] = '\0';
  292.     debugp((stderr, "\n"));
  293.     for (i = 0; i < argc; i++) {
  294.     debugp((stderr, "%s ", argv[i]));
  295.     }
  296.     debugp((stderr, "\n"));
  297.     debugp((stderr, "%s\n", date));
  298.     argc = Opt_Parse(argc, argv, OptionArray, Opt_Number(OptionArray), 0);
  299.     progArgc = argc;
  300.     progArgv = argv;
  301.  
  302.     pwPtr = getpwnam("root");
  303.     if (pwPtr != (struct passwd *) 0) {
  304.         root = pwPtr->pw_uid;
  305.     pwPtr = getpwnam("dumper");
  306.     if (pwPtr != (struct passwd *) 0) {
  307.         dumper = pwPtr->pw_uid;
  308.         euid = geteuid();
  309.         if (euid == root && setreuid(dumper, -1) != 0) {
  310.         perror("Couldn't set real userID to dumper");
  311.         exit(1);
  312.         }
  313.     }
  314.     }
  315.     endpwent();
  316.  
  317.     if ((TAR_BLOCK_SIZE & (512 - 1)) != 0) {
  318.     fatal("Tar block size must be multiple of 512\n");
  319.     }
  320.     tarBlocks = TAR_BLOCK_SIZE / 512;
  321.     oldFormat = 0;
  322.     openLog();
  323.     if (archiveFileName == NULL) {
  324.     fatal("No archive file specified");
  325.     }
  326.     tapeLevel = dumpLevel;
  327.     if (tapeNumber != 0) {
  328.     openArchiveFile();
  329.     initializeTape();
  330.     close(archivefd);
  331.     if (argc < 2) {
  332.         exit(EXIT_SUCCESS);
  333.     }
  334.     }
  335.     openArchiveFile();
  336.     if (archiveFileIsATapeDrive) {
  337.     readTapeLabel();
  338.     if (reInitialize || reInitializeSafe) {
  339.         if (reInitializeSafe) {
  340.         checkTape();
  341.         }
  342.         initializeTape();
  343.         close(archivefd);
  344.         if (argc < 2) {
  345.         exit(EXIT_SUCCESS);
  346.         }
  347.         openArchiveFile();
  348.     }
  349.     }
  350.     if (printTOC) {
  351.     if (!archiveFileIsATapeDrive) {
  352.         fatal("Cannot print TOC: Archive is not a tapeDrive");
  353.     }
  354.     fprintf(stderr, "%s\n", tapeBuffer);
  355.     if (argc < 2) {
  356.         exit(EXIT_SUCCESS);
  357.     }
  358.     }
  359.     if (argc < 2) {
  360.     Opt_PrintUsage(argv[0], OptionArray, Opt_Number(OptionArray));
  361.     exit(EXIT_FAILURE);
  362.     }
  363. #ifdef PROG_DUMP
  364.     directoryToDump = argv[1];
  365.     debugp((stderr, "dumping %s\n", directoryToDump));
  366.     if (archiveFileIsATapeDrive) {
  367.     setFileNumber();
  368.     if (oldFormat) {
  369.         skipOverFiles();
  370.     } else {
  371.         /* 
  372.          * We are currently at the end of the label since we just read
  373.          * it.  The tar file will follow the subsequent file mark.
  374.          */
  375.         status = skipFiles(1);
  376.         if (status != SUCCESS) {
  377.         fatal("Can't skip over last filemark\n");
  378.         }
  379.     }
  380.     }
  381.     getDumpDate();
  382.     forkOffTar();
  383.     dumpDirectory(directoryToDump);
  384.     flushOutput();
  385.     waitForChildToDie();
  386.     openArchiveFile();
  387.     if (fatalErrors) {
  388.     sendMail("Dump failed with fatal errors");
  389.     } else {
  390.     if (nonFatalErrors) {
  391.         sendMail("Dump completed with non-fatal errors.");
  392.     } else {
  393.         sendMail("Dump completed successfully.");
  394.     }
  395.     recordTime();
  396.     }
  397.     debugp((stderr, "finished dumping %s, %.1lf MBytes\n",
  398.         directoryToDump, (double) totalBytes / (double) MBytes(1)));
  399. #else /* PROG_DUMP */
  400.     assert(progArgc >= 2);
  401.     if (fileNumber == 0) {
  402.     setFileNumber();
  403.     } else {
  404.     findLastFile();
  405.     }
  406.     skipOverFiles();
  407.     forkOffTar();
  408.     waitForChildToDie();
  409.     openArchiveFile();
  410.     rewindTape();
  411. #endif /* PROG_DUMP */
  412.     debugp((stderr,
  413.     "%s exiting, there were %d non-fatal errors, %d hard errors\n",
  414.     argv[0], nonFatalErrors, fatalErrors));
  415.     exit(fatalErrors);
  416. }
  417.  
  418. /*
  419.  *----------------------------------------------------------------------
  420.  *
  421.  * dumpDirectory --
  422.  *
  423.  *      Procedure to dump a directory tree.  This routine does an
  424.  *      inorder traversal of a directory.  It calls itself recursively
  425.  *      to dump each subdirectory.
  426.  *
  427.  * Results:
  428.  *      None.
  429.  * 
  430.  * Side effects:
  431.  *      Depends on the options, but normally the files in the specified
  432.  *      directory are dumped.
  433.  *  
  434.  *----------------------------------------------------------------------
  435.  */ 
  436.  
  437. static void
  438. dumpDirectory(dir)
  439.     char *dir;
  440. {
  441.     char pathname[MAXPATHLEN];
  442.     char backslash_pathname[MAXPATHLEN];
  443.     DIR *dirDesc;
  444.     struct direct *d;
  445.     int slash;
  446.  
  447.     if ((dirDesc = opendir(dir)) == NULL) {
  448.     warning("Cannot open directory `%s'", dir);
  449.     ++nonFatalErrors;
  450.     return;
  451.     }
  452.     slash =  (dir[strlen(dir) - 1] == '/');
  453.     while ((d = readdir(dirDesc)) != NULL) {
  454.     struct stat statBuf;
  455.  
  456.     if (*d->d_name == '.') {
  457.         if (d->d_name[1] == 0)
  458.         continue;
  459.         if (d->d_name[1] == '.' && d->d_name[2] == 0)
  460.         continue;
  461.     }
  462.     (void) sprintf(pathname, slash ? "%s%s" : "%s/%s", dir, d->d_name);
  463.     if (lstat(pathname, &statBuf)) {
  464.         warning("can't lstat %s", pathname);
  465.         ++nonFatalErrors;
  466.         continue;
  467.     }
  468.     quote_string(backslash_pathname, pathname);
  469.     if (statBuf.st_mtime >= lastTime || statBuf.st_ctime >= lastTime) {
  470.         if (puts(backslash_pathname) == EOF) {
  471.         (void) fprintf(stderr, "error in puts\n");
  472.         ++fatalErrors;
  473.         } else if (verbose) {
  474.         fprintf(stderr, "dumping %s\n", backslash_pathname);
  475.         }
  476.         totalBytes += statBuf.st_size;
  477.     }
  478.     if (((statBuf.st_mode & S_IFDIR) == S_IFDIR) && 
  479.         ((statBuf.st_mode & S_IFRLNK) != S_IFRLNK) &&
  480.         ((statBuf.st_mode & S_IFPDEV) != S_IFPDEV)) {
  481.         dumpDirectory(pathname);
  482.     }
  483.     }
  484.     (void) closedir(dirDesc);
  485.     return;
  486. }
  487.  
  488. static struct {
  489.     int     tape;
  490.     int     file;
  491.     int     level;
  492.     double  mbytes;
  493.     double  remaining;
  494.     double  errorRate;
  495.     time_t  time;
  496.     char    dirname[MAXPATHLEN];
  497. } dumpDateEntry;
  498.  
  499. #ifdef PROG_DUMP
  500. /*
  501.  *----------------------------------------------------------------------
  502.  *
  503.  * recordTime --
  504.  *
  505.  *    Append the start time of the current dump to the dump database.
  506.  *
  507.  * Results:
  508.  *      None.    
  509.  * 
  510.  * Side effects:
  511.  *      The start time of the current dump is appended to the end
  512.  *      of the dump database.  A fatal error occurs if the database
  513.  *      doesn't exist or is unwritable.
  514.  *      
  515.  *----------------------------------------------------------------------
  516.  */ 
  517.  
  518. static void
  519. recordTime()
  520. {
  521.     FILE         *fp = NULL;
  522.     char         *date;
  523.     Dev_TapeStatus    tapeStatus;
  524.     int            errors;
  525.     double        mbytes;
  526.     double        errorRate;
  527.     ReturnStatus    status = FAILURE;
  528.     double        remaining;
  529.     double        mbytesPerBlock;
  530.     char        *name = "UNKNOWN"; 
  531.     char        *serial = "UNKNOWN";
  532.     int            blocks;
  533.     char        shortDate[16];
  534.     char         buf[128];
  535.  
  536.     if (official) {
  537.     if ((fp = fopen(DUMPDATES, "a")) == NULL) {
  538.         fatal("Can't open %s", DUMPDATES);
  539.     }
  540.     }
  541.     date = asctime(localtime(&startTime));
  542.     date[24] = '\0';
  543.     mbytes = ((double) totalBytes) / ((double) MBytes(1));
  544.     debugp((stderr, "mbytes = %lf\n", mbytes));
  545.     errorRate = -1;
  546.     remaining = -1;
  547.     if (!oldFormat) {
  548.     bzero((char *) &tapeStatus, sizeof(tapeStatus));
  549.     debugp((stderr, "Getting tape status\n"));
  550.     status = Fs_IOControl(archivefd, IOC_TAPE_STATUS, 0, NULL, 
  551.         sizeof(tapeStatus), &tapeStatus);
  552.     if (status == SUCCESS) {
  553.         mbytesPerBlock = 
  554.         (double) tapeStatus.blockSize / (double) MBytes(1);
  555.         debugp((stderr, "position = %d, remaining = %d\n",
  556.             tapeStatus.position, tapeStatus.remaining));
  557.         blocks = tapeStatus.position - tapePosition;
  558.         mbytes = blocks * mbytesPerBlock;
  559.         errors = tapeStatus.readWriteRetry + tapeStatus.dataError;
  560.         errorRate = ((double) errors / (double) blocks) * 100.0;
  561.         remaining = tapeStatus.remaining * mbytesPerBlock;
  562.         debugp((stderr, 
  563.         "mbytes = %lf,  errorRate = %lf, remaining = %lf\n",
  564.         mbytes, errorRate, remaining));
  565.     }
  566.     }
  567.     (void) sprintf(buf, "%03d %03d %d %6.1lf %6.1lf %s  %s\n",
  568.            tapeNumber, fileNumber, dumpLevel, mbytes, remaining,
  569.            date, directoryToDump);
  570.     if (archiveFileIsATapeDrive) {
  571.     strcat(tapeBuffer, buf);
  572.     writeTapeLabel();
  573.     if (close(archivefd) != 0) {
  574.         fatal("Close of archive failed");
  575.     }
  576.     }
  577.     if (official) {
  578.     fprintf(fp, "%s", buf);
  579.     (void) fclose(fp);
  580.     }
  581.  
  582.     if ((fp = fopen(DRIVELOG, "a")) == NULL) {
  583.     fatal("Can't open %s", DRIVELOG);
  584.     }
  585.     if (status == SUCCESS) {
  586.     switch(tapeStatus.type) {
  587.         case DEV_TAPE_EXB8200:
  588.         name = "EXB-8200";
  589.         break;
  590.         case DEV_TAPE_EXB8500:
  591.         name = "EXB-8500";
  592.         break;
  593.         case DEV_TAPE_TLZ04:
  594.         name = "DEC-TLZ04";
  595.         break;
  596.         default: {
  597.         if (tapeStatus.type & DEV_TAPE_8MM) {
  598.             name = "UNKNOWN-8MM";
  599.         } else if (tapeStatus.type & DEV_TAPE_4MM) {
  600.             name = "UNKNOWN-4MM";
  601.         }
  602.         }
  603.     }
  604.     if (tapeStatus.serial[0] != '\0') {
  605.         serial = tapeStatus.serial;
  606.     }
  607.     }
  608.     bcopy(&date[4], shortDate, 7);
  609.     bcopy(&date[20], &shortDate[7], 4);
  610.     shortDate[11] = '\0';
  611.     fprintf(fp, "%-10s %-10s %3d %7.1lf %5.1lf%% %s %s\n", name, serial,
  612.     tapeNumber, mbytes, errorRate, shortDate, archiveFileName);
  613.     (void) fclose(fp);
  614.  
  615.     return;
  616. }
  617.  
  618. /*
  619.  *----------------------------------------------------------------------
  620.  *
  621.  * getNextDumpDateEntry --
  622.  *
  623.  *    Reads the next entry from the dump database file,
  624.  *    and puts the information into a structure.
  625.  *
  626.  * Results:
  627.  *    Returns non-zero if the next entry is read successfully.
  628.  * 
  629.  * Side effects:
  630.  *      A fatal error occurs if the database doesn't exist, is unreadable
  631.  *      or if it is improperly formated.
  632.  *      
  633.  *----------------------------------------------------------------------
  634.  */ 
  635. static int
  636. getNextDumpDateEntry()
  637. {
  638.     static FILE *fp;
  639.     static int lineCnt;
  640.     char buf[0x1000];
  641.     char *s;
  642.  
  643.     if (fp == NULL) {
  644.     if ((fp = fopen(DUMPDATES, "r")) == NULL) {
  645.         fatal("Can't open %s", DUMPDATES);
  646.     }
  647.     }
  648.  
  649.     /*
  650.      * read in the file line by line until we get a valid entry.
  651.      */
  652.     while (fgets(buf, sizeof(buf), fp)) {
  653.     ++lineCnt;
  654.     /*
  655.      * If the line is empty, only white space, or is a
  656.      * comment, then throw it away and continue.
  657.      */
  658.     s = buf;
  659.     while (*s == ' ' || *s == '\t') {
  660.         ++s;
  661.     }
  662.     if (*s == '#' || *s == '\n' || *s == '\0') {
  663.         continue;
  664.     }
  665.     if (parseDumpInfo(s) == 0) {
  666.         fatal("format error in %s: line %d |%s|",
  667.         DUMPDATES, lineCnt, buf);
  668.     }
  669.     return 1;
  670.     }
  671.     (void) fclose(fp);
  672.     return 0;
  673. }
  674. #endif
  675.  
  676. static int
  677. parseDumpInfo(buf)
  678.     char *buf;
  679. {
  680.     extern time_t mktime();
  681.     static char months[][4] = {
  682.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  683.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  684.     };
  685.     struct tm tm;
  686.     char *s;
  687.     int i;
  688.     int n;
  689.     int    token = 1;
  690.  
  691.     bzero((char *) &dumpDateEntry, sizeof(dumpDateEntry));
  692.     /*
  693.      * The first token is the tape number
  694.      */
  695.     if ((s = strtok(buf, " \t\n")) == NULL || !isdigit(*s)) {
  696.     goto mismatch;
  697.     }
  698.     dumpDateEntry.tape = atoi(s);
  699.     token++;
  700.     /*
  701.      * The next token is the file number
  702.      */
  703.     if ((s = strtok(NULL, " \t\n")) == NULL || !isdigit(*s)) {
  704.     goto mismatch;
  705.     }
  706.     dumpDateEntry.file = atoi(s);
  707.     token++;
  708.  
  709.     /* 
  710.      * The next token should be a single digit in the range 0-9 that
  711.      * indicates the level of the dump.
  712.      */
  713.     s = strtok((char *) NULL, " \t\n");
  714.     if (s == NULL || !isdigit(*s) || strlen(s) != 1) {
  715.     goto mismatch;
  716.     }
  717.     dumpDateEntry.level = *s - '0';
  718.     token++;
  719.  
  720.     /* the next token should be the number of bytes */
  721.     s = strtok((char *) NULL, " \t\n");
  722.     if (strchr(s, (int) '.')) {
  723.     /* Number of MBytes. */
  724.     n = sscanf(s, "%lf", &dumpDateEntry.mbytes);
  725.     if (n != 1) {
  726.         goto mismatch;
  727.     }
  728.     token++;
  729.     /* Number of remaining MBytes on tape. */
  730.     s = strtok((char *) NULL, " \t\n");
  731.     n = sscanf(s, "%lf", &dumpDateEntry.remaining);
  732.     if (n != 1) {
  733.         goto mismatch;
  734.     }
  735.     token++;
  736.     } else {
  737.     n = sscanf(s, "%d", &i);
  738.     if (n != 1) {
  739.         goto mismatch;
  740.     }
  741.     }
  742.     /*
  743.      * The time should be formated just like the return string
  744.      * from asctime(3).  So, parse the string and make sure the
  745.      * format is correct.
  746.      */
  747.  
  748.     if ((s = strtok((char *) NULL, " \t")) == NULL) {
  749.     goto mismatch;
  750.     }
  751.     token++;
  752.     if ((s  = strtok((char *) NULL, " ")) == NULL) {
  753.     goto mismatch;
  754.     }
  755.     token++;
  756.     for (i = 13; --i >= 0;) {
  757.     if (strcmp(months[i], s) == 0) {
  758.         break;
  759.     }
  760.     }
  761.     if ((tm.tm_mon = i) < 0) {
  762.     goto mismatch;
  763.     }
  764.     if ((s = strtok((char *) NULL, " ")) == NULL) {
  765.     goto mismatch;
  766.     }
  767.     token++;
  768.     tm.tm_mday = atoi(s);
  769.     if ((s = strtok((char *) NULL, ":")) == NULL) {
  770.     goto mismatch;
  771.     }
  772.     token++;
  773.     tm.tm_hour = atoi(s);
  774.     if ((s = strtok((char *) NULL, ":")) == NULL) {
  775.     goto mismatch;
  776.     }
  777.     token++;
  778.     tm.tm_min = atoi(s);
  779.     if ((s = strtok((char *) NULL, " ")) == NULL) {
  780.     goto mismatch;
  781.     }
  782.     token++;
  783.     tm.tm_sec = atoi(s);
  784.     if ((s = strtok((char *) NULL, " \t\n")) == NULL) {
  785.     goto mismatch;
  786.     }
  787.     tm.tm_year = atoi(s) - 1900;
  788.     /* Convert to old-fashioned calander time */
  789.     if((dumpDateEntry.time = mktime(&tm)) == -1) {
  790.     debugp((stderr, "parseDumpInfo:  mktime failed\n"));
  791.     return 0;
  792.     }
  793.  
  794.     token++;
  795.     if ((s = strtok((char *) NULL, " \t\n")) == NULL) {
  796.     goto mismatch;
  797.     }
  798.  
  799.     /*
  800.      * The remainder of the line is the directory name.
  801.      */
  802.     strcpy(dumpDateEntry.dirname, s);
  803.     return 1;
  804. mismatch:
  805.     debugp((stderr, "parseDumpInfo:  parse error on token %d \"%s\"\n", 
  806.         token, s));
  807.     return 0;
  808.  
  809. }
  810.  
  811.  
  812. #ifdef PROG_DUMP
  813. /*
  814.  *----------------------------------------------------------------------
  815.  *
  816.  * getDumpDate --
  817.  *
  818.  *    Reads the dump database file, and determines the last time
  819.  *      that a lower level dump of the directory was done.
  820.  *
  821.  * Results:
  822.  *    Returns the time of the last lower level dump.
  823.  * 
  824.  * Side effects:
  825.  *      A fatal error occurs if the database doesn't exist, is unreadable
  826.  *      or if it is improperly formated.
  827.  *      
  828.  *----------------------------------------------------------------------
  829.  */ 
  830.  
  831. static void
  832. getDumpDate()
  833. {
  834.     time_t t = 0;
  835.  
  836.     while (getNextDumpDateEntry()) {
  837.     if (strcmp(dumpDateEntry.dirname, directoryToDump) != 0) {
  838.         continue;
  839.     }
  840.     if (dumpDateEntry.level < dumpLevel) {
  841.         t = dumpDateEntry.time;
  842.     }
  843.     }
  844.     lastTime = t;
  845.     return;
  846. }
  847. #endif
  848.  
  849. /*
  850.  *----------------------------------------------------------------------
  851.  *
  852.  * openArchiveFile --
  853.  *
  854.  *    Opens the archive file and checks to see if it is a tapedrive.
  855.  *
  856.  * Results:
  857.  *    None
  858.  * 
  859.  * Side effects:
  860.  *      Opens the archive file.
  861.  *      
  862.  *----------------------------------------------------------------------
  863.  */ 
  864.  
  865. static void
  866. openArchiveFile()
  867. {
  868.     struct stat statBuf;
  869.     extern int Fs_GetAttributes();
  870.     Fs_Attributes attrs;
  871.     Dev_TapeStatus    tapeStatus;
  872.     ReturnStatus    status;
  873.  
  874.     debugp((stderr, "opening %s as archive file\n", archiveFileName));
  875. #ifdef PROG_DUMP
  876.     if (strcmp(archiveFileName, "-") == 0) {
  877.     archivefd = 1;
  878.     } else if ((archivefd = open(archiveFileName,O_RDWR)) < 0) {
  879.     if ((archivefd = open(archiveFileName,
  880.                   O_RDWR|O_CREAT, 0664)) < 0) {
  881.         fatal("Can't open `%s'", archiveFileName);
  882.     }
  883.     }
  884. #else    
  885.     if (strcmp(archiveFileName, "-") == 0) {
  886.     archivefd = 0;
  887.     } else if ((archivefd = open(archiveFileName,O_RDONLY)) < 0) {
  888.     fatal("Can't open `%s'", archiveFileName);
  889.     }
  890. #endif
  891.     if (fstat(archivefd, &statBuf)) {
  892.     fatal("Cannot stat %s", archiveFileName);
  893.     }
  894.     switch (statBuf.st_mode & S_IFMT) {
  895.  
  896.     case S_IFREG:        /* regular file */
  897.         break;
  898.  
  899.     case S_IFCHR:        /* character dev. -- probably a tape drive */
  900.     if (Fs_GetAttributes(archiveFileName, 0, &attrs) != SUCCESS) {
  901.         fatal("Cannot get attributes of %s", archiveFileName);
  902.     }
  903.     if (attrs.devType == 5) {
  904.         archiveFileIsATapeDrive = TRUE;
  905.         bzero((char *) &tapeStatus, sizeof(tapeStatus));
  906.         status = Fs_IOControl(archivefd, IOC_TAPE_STATUS, 0, NULL, 
  907.         sizeof(tapeStatus), &tapeStatus);
  908.         debugp((stderr, "IOC_TAPE_STATUS returned 0x%x\n", status));
  909.         if (status != SUCCESS) {
  910.         oldFormat = TRUE;
  911.         debugp((stderr, "Using old format.\n", status));
  912.         } else {
  913.         debugp((stderr, "tapeStatus.type is 0x%x\n", tapeStatus.type));
  914.         if (tapeStatus.type == DEV_TAPE_EXB8200) {
  915.             oldFormat = TRUE;
  916.             debugp((stderr, "Using old format.\n", status));
  917.         }
  918.  
  919. #ifndef PROG_DUMP
  920.         if ((tapeStatus.type == DEV_TAPE_EXB8500) &&
  921.            (tapeStatus.density == DEV_EXB8500_8200_MODE)) {
  922.             oldFormat = TRUE;
  923.             debugp((stderr, "Using old format.\n", status));
  924.         }
  925. #endif
  926.         }
  927.         break;
  928.     }
  929.     /* FALLTHROUGH */
  930.     default:
  931.     warning("%s: not a normal file or tape drive", archiveFileName);
  932.     break;
  933.     }
  934.     return;
  935. }
  936.  
  937. /*
  938.  *----------------------------------------------------------------------
  939.  *
  940.  * forkOffTar --
  941.  *
  942.  *    Forks off tar and pipes stdout into it.
  943.  *
  944.  * Results:
  945.  *    None
  946.  * 
  947.  * Side effects:
  948.  *      Creates a child process.
  949.  *      
  950.  *----------------------------------------------------------------------
  951.  */ 
  952. static void
  953. forkOffTar()
  954. {
  955.     char         tarargs[20];
  956.     char         blocks[20];
  957.     Dev_TapeStatus    tapeStatus;
  958.     ReturnStatus    status;
  959. #ifdef PROG_RESTORE
  960.     char **arg;
  961.     int i, j;
  962. #endif
  963.  
  964.     if (!oldFormat) {
  965.     bzero((char *) &tapeStatus, sizeof(tapeStatus));
  966.     status = Fs_IOControl(archivefd, IOC_TAPE_STATUS, 0, NULL, 
  967.         sizeof(tapeStatus), &tapeStatus);
  968.     if (status != SUCCESS) {
  969.         debugp((stderr, "IOC_TAPE_STATUS returned 0x%x\n", status));
  970.     } else {
  971.         tapePosition = tapeStatus.position;
  972.         debugp((stderr, "position = %d\n", tapePosition));
  973.     }
  974.     }
  975. #ifdef PROG_DUMP    
  976.  
  977.     if (pipe(pipefd) < 0) {
  978.     fatal("Cannot open pipe");
  979.     }
  980.     switch (tarChild = fork()) {
  981.  
  982.     case -1:
  983.     fatal("Can't fork");
  984.  
  985.     case 0:
  986.     (void) close(pipefd[1]);
  987.     if (dup2(archivefd, 1) < 0) {
  988.         fatal("dup2");
  989.     }
  990.     if (dup2(pipefd[0], 0) < 0) {
  991.         fatal("dup2");
  992.     }
  993.     *tarargs = '\0';
  994.     if (resetAccessTimes) {
  995.         strcat(tarargs, "a");
  996.     }
  997.     if (verbose) {
  998.         strcat(tarargs, "v");
  999.     }
  1000.     if (debug) {
  1001.         strcat(tarargs, "e");
  1002.     }
  1003.     if (oldFormat) {
  1004.         strcat(tarargs, "ncfTPL");
  1005.         debugp((stderr, "execing tar %s - -\n", tarargs));
  1006.         execlp(TAR, TAR, tarargs, "-", "-", NULL);
  1007.     } else {
  1008.         strcat(tarargs, "ncbfTPL");
  1009.         sprintf(blocks, "%d", tarBlocks);
  1010.         debugp((stderr, "execing tar %s %s - -\n", tarargs, blocks));
  1011.         execlp(TAR, TAR, tarargs, blocks, "-", "-", NULL);
  1012.     }
  1013.     fatal("exec failed");
  1014.  
  1015.     default:
  1016.     (void) close(pipefd[0]);
  1017.     if (dup2(pipefd[1], 1)) {
  1018.         fatal("dup2");
  1019.     }
  1020.     }
  1021. #else
  1022.  
  1023.     sprintf(blocks, "%d", tarBlocks);
  1024.     close(archivefd);
  1025.     switch (tarChild = fork()) {
  1026.  
  1027.     case -1:
  1028.     fatal("Can't fork");
  1029.  
  1030.     case 0: {
  1031.     char **ptr;
  1032.     arg = (char **) malloc(sizeof(char **) * (progArgc + 5));
  1033.     ptr = arg;
  1034.     *ptr++ = TAR;
  1035.     if (printContents) {
  1036.         strcpy(tarargs, "tv");
  1037.     } else {
  1038.         strcpy(tarargs, "x");
  1039.     }
  1040.     if (oldFormat) {
  1041.         strcat(tarargs, "pf");
  1042.     } else {
  1043.         strcat(tarargs, "pfb");
  1044.     }
  1045.     if (verbose) {
  1046.         strcat(tarargs, "v");
  1047.     }
  1048.     if (!relativePaths) {
  1049.         strcat(tarargs, "P");
  1050.     }
  1051.     if (debug) {
  1052.         strcat(tarargs, "e");
  1053.     }
  1054.     *ptr++ = tarargs;
  1055.     *ptr++ = archiveFileName;
  1056.     if (!oldFormat) {
  1057.         *ptr++ = blocks;
  1058.     }
  1059.     for (i = 1; (*ptr++ = progArgv[i]) != NULL; ++i) {
  1060.         continue;
  1061.     }
  1062.     debugp((stderr, "execing tar"));
  1063.     for (j = 0; j < i + 3; j++) {
  1064.         debugp((stderr, " %s", arg[j]));
  1065.     }
  1066.     debugp((stderr, "\n"));
  1067.     execvp(TAR, arg);
  1068.     fatal("exec failed");
  1069.     }
  1070.     default:
  1071.     break;
  1072.     }
  1073. #endif    
  1074.     debugp((stderr, "successfully forked tar\n"));
  1075.     return;
  1076. }
  1077.  
  1078. #ifdef PROG_DUMP
  1079. /*
  1080.  *----------------------------------------------------------------------
  1081.  *
  1082.  * flushOutput --
  1083.  *
  1084.  *    Wait for tar to finish reading all the data in the pipe.
  1085.  *    Check the error return code.
  1086.  *
  1087.  * Results:
  1088.  *    None
  1089.  * 
  1090.  * Side effects:
  1091.  *      Closes files, increments a global variable.
  1092.  *      
  1093.  *----------------------------------------------------------------------
  1094.  */ 
  1095. static void
  1096. flushOutput()
  1097. {
  1098.  
  1099.     debugp((stderr, "flushing output\n"));
  1100.     (void) fflush(stdout);
  1101.     (void) close(1);
  1102.     (void) close(pipefd[1]);
  1103.     return;
  1104. }
  1105. #endif
  1106.  
  1107. static void
  1108. waitForChildToDie()
  1109. {
  1110.     int w;
  1111.     union wait ws;
  1112.  
  1113.     while ((w = wait(&ws)) > 0 && w != tarChild) {
  1114.     continue;
  1115.     }
  1116.     switch (ws.w_retcode) {
  1117.  
  1118.     case 0:     /* normal exit */
  1119.     break;
  1120.  
  1121.     case 1:
  1122.         fatal("tar invoked with invalid arguments");
  1123.     break;
  1124.  
  1125.     case 2:
  1126.     warning("tar encountered at least one invalid filename");
  1127.     ++nonFatalErrors;
  1128.     break;
  1129.  
  1130.     case 3:
  1131.     fatal("bad archive");
  1132.     break;
  1133.  
  1134.     case 4:
  1135.     fatal("system error in tar");
  1136.     break;
  1137.  
  1138.     default:
  1139.     fatal("tar exited with nozero status: %d", ws.w_retcode);
  1140.     break;
  1141.     }
  1142.     (void) close(archivefd);
  1143.     return;
  1144. }
  1145.  
  1146. /*
  1147.  *----------------------------------------------------------------------
  1148.  *
  1149.  * readTapeLabel --
  1150.  *
  1151.  *    Read the label on a tape, and put the label into the tapeBuffer.
  1152.  *
  1153.  * Results:
  1154.  *    None
  1155.  * 
  1156.  * Side effects:
  1157.  *      The tape is rewound.
  1158.  *      
  1159.  *----------------------------------------------------------------------
  1160.  */
  1161.  
  1162. static void
  1163. readTapeLabel()
  1164. {
  1165.     ReturnStatus    status = SUCCESS;
  1166.     int            n;
  1167.     int            bytesRead;
  1168.     Dev_TapeStatus    tapeStatus;
  1169.  
  1170.     debugp((stderr, "reading tape label\n"));
  1171.     labelSize = LABEL_SIZE_OLD;
  1172.     bzero((char *) &tapeStatus, sizeof(tapeStatus));
  1173.     status = Fs_IOControl(archivefd, IOC_TAPE_STATUS, 0, NULL, 
  1174.     sizeof(tapeStatus), &tapeStatus);
  1175.     if ((status != SUCCESS) || (tapeStatus.type == DEV_TAPE_EXB8200) ||
  1176.     (reInitialize) || (reInitializeSafe)) {
  1177.     /*
  1178.      * The tape may be in the old format if the tape drive is an
  1179.      * exb8200, or if we are reinitializing an old format tape.
  1180.      * Try reading the label at the beginning of the tape.
  1181.      */
  1182.     rewindTape();
  1183.     
  1184.     bytesRead = read(archivefd, tapeBuffer, labelSize);
  1185.     debugp((stderr, "attempt to read old label read %d bytes\n", 
  1186.             bytesRead));
  1187.     if (bytesRead == labelSize) { 
  1188.         if (!strncmp(tapeBuffer, SPRITE_OLD_DUMP_HEADER, 
  1189.             strlen(SPRITE_OLD_DUMP_HEADER)) != 0) {
  1190.         oldFormat = TRUE;
  1191.         debugp((stderr, "Using old format\n"));
  1192.         n = sscanf(tapeBuffer + strlen(SPRITE_OLD_DUMP_HEADER), 
  1193.             "%d", &tapeNumber);
  1194.         if (n != 1) {
  1195.             warning("Couldn't read tape number from label\n");
  1196.         }
  1197.         } else if (oldFormat) {
  1198.         fatal("The tape does not have a correct label");
  1199.         }
  1200.     }
  1201.     }
  1202.     if (!oldFormat) {
  1203.     Boolean    beginning = FALSE;
  1204.  
  1205.     labelSize = LABEL_SIZE;
  1206.     gotoEOD();
  1207.     /*
  1208.      * Keep backing up one file at a time until we find a label, or
  1209.      * the beginning of the tape. In order to back up one file at
  1210.      * a time we must back up over both the current file and the 
  1211.      * previous file, hence the skip backwards over two files.
  1212.      * 
  1213.      */
  1214.     status = SUCCESS;
  1215.     while(status == SUCCESS) {
  1216.         status = skipFiles(-2);
  1217.         if (status == DEV_END_OF_TAPE) {
  1218.         /*
  1219.          * We must have hit the beginning of the tape.
  1220.          * Keep track so we only do this once.
  1221.          */
  1222.         debugp((stderr, "hit beginning of tape\n"));
  1223.         if (beginning == TRUE) {
  1224.             fatal("The tape does not have a correct label");
  1225.         }
  1226.         beginning = TRUE;
  1227.         status = SUCCESS;
  1228.         } else if (status == SUCCESS) {
  1229.         /*
  1230.          * We are now on the BOT side of a file mark. Skip to the
  1231.          * EOT side.
  1232.          */
  1233.         debugp((stderr, "skipping over file mark\n"));
  1234.         status = skipFiles(1);
  1235.         if (status != SUCCESS) {
  1236.             fatal("Error skipping over file mark");
  1237.         }
  1238.         }
  1239.         /*
  1240.          * Try reading the label. 
  1241.          */
  1242.         debugp((stderr, "trying to read label (%d bytes)\n",
  1243.         labelSize));
  1244.         bytesRead = read(archivefd, tapeBuffer, labelSize);
  1245.         if (bytesRead == labelSize) { 
  1246.         debugp((stderr, "read succeeded\n"));
  1247.         if (!strncmp(tapeBuffer, SPRITE_DUMP_HEADER, 
  1248.             strlen(SPRITE_DUMP_HEADER))){
  1249.             /* 
  1250.              * We found a label.
  1251.              */
  1252.             debugp((stderr, "found a label\n"));
  1253.             break;
  1254.         } else {
  1255.             debugp((stderr, "found \"%s\"\n", tapeBuffer));
  1256.         }
  1257.         } else {
  1258.         debugp((stderr, "only read %d bytes\n", bytesRead));
  1259.         }
  1260.     }
  1261.     if (status != SUCCESS) {
  1262.         fatal("The tape does not have a correct label");
  1263.     }
  1264.     n = sscanf(tapeBuffer + strlen(SPRITE_DUMP_HEADER), 
  1265.         "%*s %d %*s %d %*s %d\n", &version, &tapeLevel, 
  1266.             &tapeNumber);
  1267.     if (n != 3) {
  1268.         fatal("Couldn't read information from tape label\n");
  1269.     }
  1270.     if (version != SPRITE_DUMP_VERSION) { 
  1271.         fatal("Invalid dump tape version \"%d\"\n", version);
  1272.     }
  1273.     }
  1274.     debugp((stderr, "Tape: %d\n", tapeNumber));
  1275.     debugp((stderr, "Version: %d\n", version));
  1276.     debugp((stderr, "Level: %d\n", tapeLevel));
  1277.     debugp((stderr, "TapeLabel=|%s|\n", tapeBuffer));
  1278.     return;
  1279. }
  1280.  
  1281. #ifdef PROG_DUMP
  1282. /*
  1283.  *----------------------------------------------------------------------
  1284.  *
  1285.  * writeTapeLabel --
  1286.  *
  1287.  *    Copy the tapeBuffer onto the tape.
  1288.  *
  1289.  * Results:
  1290.  *    None
  1291.  * 
  1292.  * Side effects:
  1293.  *      The tape is rewound.
  1294.  *      
  1295.  *----------------------------------------------------------------------
  1296.  */
  1297.  
  1298. static void
  1299. writeTapeLabel()
  1300. {
  1301.  
  1302.     debugp((stderr, "writing tape label\n"));
  1303.     if (oldFormat) {
  1304.     rewindTape();
  1305.     } else {
  1306.     gotoEOD();
  1307.     }
  1308.     if (write(archivefd, tapeBuffer, labelSize) != labelSize) {
  1309.     fatal("Error writing tape label");
  1310.     }
  1311.     /*
  1312.      * Rewinding the tape prevents a file mark from being written, which
  1313.      * is what we want on the old format tapes.
  1314.      */
  1315.     if (oldFormat) {
  1316.     rewindTape();
  1317.     }
  1318.     return;
  1319. }
  1320. #endif
  1321.  
  1322. static void
  1323. initializeTape()
  1324. {   
  1325.     int nbufs;
  1326.     FILE *fp;
  1327.     Dev_TapeStatus    tapeStatus;
  1328.     int            tocSize;
  1329.     static char        tempBuffer[IOBUF_SIZE];
  1330.     ReturnStatus    status;
  1331.  
  1332.     debugp((stderr, "initializing tape #%d\n", tapeNumber));
  1333.     if (archiveFileIsATapeDrive == 0) {
  1334.     fatal("Cannot initialize:  Archive file is not a tape drive");
  1335.     }
  1336.     rewindTape();
  1337.     bzero((char *) &tapeStatus, sizeof(tapeStatus));
  1338.     status = Fs_IOControl(archivefd, IOC_TAPE_STATUS, 0, NULL, 
  1339.     sizeof(tapeStatus), &tapeStatus);
  1340.     if ((status != SUCCESS) || (tapeStatus.type == DEV_TAPE_EXB8200)) {
  1341.     oldFormat = TRUE;
  1342.     labelSize = LABEL_SIZE_OLD;
  1343.     } else {
  1344.     oldFormat = FALSE;
  1345.     labelSize = LABEL_SIZE;
  1346.     }
  1347.     memset(tapeBuffer, '\0', labelSize);
  1348.     if (oldFormat) {
  1349.     sprintf(tapeBuffer, "%s%d\n", SPRITE_OLD_DUMP_HEADER, tapeNumber);
  1350.     } else {
  1351.     char    format[80];
  1352.     strcpy(format, SPRITE_DUMP_HEADER);
  1353.     strcat(format, SPRITE_DUMP_INFO);
  1354.     sprintf(tapeBuffer, format, SPRITE_DUMP_VERSION, tapeLevel,tapeNumber);
  1355.     strcat(tapeBuffer, "\n");
  1356.     }
  1357.  
  1358.     debugp((stderr, "writing label\n"));
  1359.     if (write(archivefd, tapeBuffer, labelSize) != labelSize) {
  1360.     fatal("Write error while initializing tape label");
  1361.     }
  1362.     debugp((stderr, "done writing label\n"));
  1363.     if (oldFormat) {
  1364.     tocSize = TOC_SIZE_OLD;
  1365.     } else {
  1366.     tocSize = TOC_SIZE;
  1367.     }
  1368.     debugp((stderr, "writing padding\n"));
  1369.     memset(tempBuffer, '\0', sizeof(tempBuffer));
  1370.     for (nbufs = tocSize / IOBUF_SIZE; --nbufs > 0;) {
  1371.     if (write(archivefd, tempBuffer,
  1372.           sizeof(tempBuffer)) != sizeof(tempBuffer)) {
  1373.         fatal("Write error while initializing tape label");
  1374.     }
  1375.     }
  1376.     debugp((stderr, "done writing padding\n"));
  1377.     if (!oldFormat) {
  1378.     Dev_TapeCommand args;
  1379.     args.command = IOC_TAPE_WEOF;
  1380.     args.count = 1;
  1381.     status = Fs_IOControl(archivefd, IOC_TAPE_COMMAND, sizeof(args),
  1382.             (Address)&args, 0, (Address) 0);
  1383.     if (status != SUCCESS) {
  1384.         fatal("Can't write file mark(s), status = 0x%x", status);
  1385.         exit(status);
  1386.     }
  1387.     }
  1388.     rewindTape();
  1389.     if (official) {
  1390.     if ((fp = fopen(DUMPDATES, "a")) == NULL) {
  1391.         fatal("Can't open %s", DUMPDATES);
  1392.     }
  1393.     /*
  1394.      *   Put a comment in the dump data file.
  1395.      */
  1396.     fprintf(fp, "# Initializing tape number %03d\n", tapeNumber);
  1397.     (void) fclose(fp);
  1398.     }
  1399.     return;
  1400. }
  1401.  
  1402. static void
  1403. rewindTape()
  1404. {
  1405.     int oldOffset;
  1406.     int status;
  1407.  
  1408.     debugp((stderr, "rewinding tape ...\n"));
  1409.     status = Ioc_Reposition(archivefd, IOC_BASE_ZERO, 0, &oldOffset);
  1410.     if (status != SUCCESS) {
  1411.     fatal("Can't rewind tape drive, status = 0x%08x", status);
  1412.     }
  1413.     debugp((stderr, "done rewinding tape.\n"));
  1414.     return;
  1415. }
  1416.  
  1417. static void
  1418. setFileNumber()
  1419. {
  1420.     char *s;
  1421. #ifdef PROG_DUMP
  1422.     fileNumber = 1;
  1423.     for (s = tapeBuffer; *s != '\0'; ++s) {
  1424.     if (s[0] == '\n' && s[1] > ' ') {
  1425.         ++fileNumber;
  1426.     }
  1427.     }
  1428. #else
  1429.     char *end;
  1430.     int len = 0;
  1431.     int n = 1;
  1432.  
  1433.     /*
  1434.      * Check each file on the dumptape, and pick the one that is the
  1435.      * longest prefix of the file to be restored.
  1436.      */
  1437.  
  1438.     if ((end = strchr(tapeBuffer, '\n')) == NULL) {
  1439.     fatal("Bad tape label\n");
  1440.     }
  1441.     for (s = end; *s != '\0'; ++n) {
  1442.     s = end + 1;
  1443.     if ((end = strchr(s, '\n')) == NULL) {
  1444.         break;
  1445.     }
  1446.     *end = '\0';
  1447.     if (parseDumpInfo(s) == 0) {
  1448.         fatal("format error in tapelabel, line %d\n", n);
  1449.     }
  1450.     assert(dumpDateEntry.file == n);
  1451.     lastFile = n;
  1452.     if (strlen(dumpDateEntry.dirname) >= len) {
  1453.         if (strncmp(dumpDateEntry.dirname, progArgv[1],
  1454.                 strlen(dumpDateEntry.dirname)) == 0) {
  1455.                 len = strlen(dumpDateEntry.dirname);
  1456.         fileNumber = n;
  1457.             }
  1458. #if 0        
  1459.         else if (dumpDateEntry.dirname[0] == '/') {
  1460.         if (strncmp(dumpDateEntry.dirname + 1, progArgv[1],
  1461.                     strlen(dumpDateEntry.dirname) - 1) == 0) {
  1462.             len = strlen(dumpDateEntry.dirname) - 1;
  1463.             fileNumber = n;
  1464.                 }
  1465.         }
  1466. #endif        
  1467.     }
  1468.     }
  1469.     (void) fprintf(stderr, "Using file #%d\n", fileNumber);
  1470.     if (fileNumber == 0) {
  1471.     fatal("None of the files on this tape contain %s.\n", progArgv[1]);
  1472.     }
  1473. #endif    
  1474.     return;
  1475. }
  1476.  
  1477. #ifdef PROG_RESTORE
  1478. static void
  1479. findLastFile()
  1480. {
  1481.     char *s;
  1482.     int n = 1;
  1483.     char *end;
  1484.  
  1485.     if ((end = strchr(tapeBuffer, '\n')) == NULL) {
  1486.     fatal("Bad tape label\n");
  1487.     }
  1488.     for (s = end; *s != '\0'; ++n) {
  1489.     s = end + 1;
  1490.     if ((end = strchr(s, '\n')) == NULL) {
  1491.         break;
  1492.     }
  1493.     *end = '\0';
  1494.     lastFile = n;
  1495.     }
  1496. }
  1497. #endif /* PROG_RESTORE */
  1498.  
  1499. static void
  1500. skipOverFiles()
  1501. {
  1502.     int         status;
  1503.     int             num;
  1504. #ifdef PROG_DUMP
  1505.     Dev_TapeCommand     args;
  1506. #endif
  1507.  
  1508.     assert(fileNumber);
  1509.     if (oldFormat) {
  1510.     rewindTape();
  1511.     num = fileNumber;
  1512.     } else {
  1513.     /*
  1514.      * In the new format we don't rewind the tape.  Instead we back
  1515.      * up from where we currently are to the file we want.
  1516.      */
  1517.     num = - (lastFile - fileNumber + 1) * 2;
  1518.     }
  1519.     status = skipFiles(num);
  1520.     if (status != SUCCESS) {
  1521.     fatal("Can't skip files, status = 0x%08x", status);
  1522.     }
  1523. #ifdef PROG_DUMP
  1524.     if (oldFormat) {
  1525.     debugp((stderr, "Backing up over filemark\n"));
  1526.     status = skipFiles(-1);
  1527.     if (status != SUCCESS) {
  1528.         fatal("Can't skip files, status = 0x%08x", status);
  1529.     }
  1530.     } 
  1531.     debugp((stderr, "rewriting file mark\n"));
  1532.     args.command = IOC_TAPE_WEOF;
  1533.     args.count = 1;
  1534.     status = Fs_IOControl(archivefd, IOC_TAPE_COMMAND, sizeof(args),
  1535.               (char *) &args, 0, (char *) 0);
  1536. #else
  1537.     if (!oldFormat) {
  1538.     /*
  1539.      * Since we backed up we are on the BOT side of a file mark.
  1540.      * Skip over it.
  1541.      */
  1542.     debugp((stderr, "Skipping over filemark\n"));
  1543.     status = skipFiles(1);
  1544.     if (status != SUCCESS) {
  1545.         fatal("Can't skip files, status = 0x%08x", status);
  1546.     }
  1547.     }
  1548. #endif
  1549.     debugp((stderr, "successfully skipped %d files\n", fileNumber));
  1550.     return;
  1551. }
  1552.  
  1553. /*ARGSUSED*/
  1554. static void
  1555. cleanup_sighup(sig)
  1556.     int sig;
  1557. {
  1558.  
  1559.     fatal("Received SIGHUP signal, terminating abnormally");
  1560.     return;
  1561. }
  1562.  
  1563. /*ARGSUSED*/
  1564. static void
  1565. cleanup_sigint(sig)
  1566.     int sig;
  1567. {
  1568.  
  1569.     fatal("Received SIGINT signal, terminating abnormally");
  1570.     return;
  1571. }
  1572.  
  1573. /*ARGSUSED*/
  1574. static void
  1575. cleanup_sigquit(sig)
  1576.     int sig;
  1577. {
  1578.  
  1579.     fatal("Received SIGQUIT signal, terminating abnormally");
  1580.     return;
  1581. }
  1582.  
  1583. /*ARGSUSED*/
  1584. static void
  1585. cleanup_sigpipe(sig)
  1586.     int sig;
  1587. {
  1588. #if 1
  1589. {
  1590.     int w;
  1591.     union wait ws;
  1592.  
  1593.     debugp((stderr, "Received SIGPIPE signal, terminating abnormally\n"));
  1594.     while ((w = wait(&ws)) > 0 && w != tarChild) {
  1595.     continue;
  1596.     }
  1597.     debugp((stderr, "SIGPIPE: tar exited with code = 0x%x\n", ws.w_retcode));
  1598.  
  1599.     if (ws.w_retcode) {
  1600.     warning("tar exited with nozero status: %d", ws.w_retcode);
  1601.     ++fatalErrors;
  1602.     }
  1603.     (void) close(archivefd);
  1604. }
  1605. #endif
  1606.  
  1607.     fatal("Received SIGPIPE signal, terminating abnormally");
  1608.     return;
  1609. }
  1610.  
  1611. /*ARGSUSED*/
  1612. static void
  1613. cleanup_sigterm(sig)
  1614.     int sig;
  1615. {
  1616.  
  1617.     fatal("Received SIGTERM signal, terminating abnormally");
  1618.     return;
  1619. }
  1620.  
  1621. /*
  1622.  *----------------------------------------------------------------------
  1623.  *
  1624.  * sendMail --
  1625.  *
  1626.  * Results:
  1627.  *    None.
  1628.  *
  1629.  * Side effects:
  1630.  *    Sends mail to the person specified by the -m option.
  1631.  *
  1632.  *----------------------------------------------------------------------
  1633.  */
  1634.  
  1635. static void
  1636. sendMail(msg)
  1637.     const char *msg;
  1638. {
  1639.     int p[2];
  1640.     int childPid;
  1641.     int w;
  1642.     FILE *fp;
  1643.  
  1644.     if (mailWho == NULL) {
  1645.     return;
  1646.     }
  1647.     pipe(p);
  1648.  
  1649.     fprintf(stderr, "sending mail to `%s'\n", mailWho);
  1650.  
  1651.     switch (childPid = fork()) {
  1652.  
  1653.     case -1:
  1654.     fatal("Fork failed");
  1655.  
  1656.     case 0: /* child */
  1657.     close(pipefd[1]);
  1658.     dup2(pipefd[0], 0);
  1659.     execlp("mail", "mail", mailWho, NULL);
  1660.     fatal("Can't exec `mail'");
  1661.     /* NOTREACHED */
  1662.  
  1663.     default: /* parent */
  1664.         close(pipefd[0]);
  1665.     fp = fdopen(pipefd[1], "w");
  1666.     fprintf(fp, "%s.\n\n", msg);
  1667.     fprintf(fp, "Level %d dump of %s on %s",
  1668.         dumpLevel, directoryToDump,
  1669.         asctime(localtime(&startTime)));
  1670.     (void) fclose(fp);
  1671.     while ((w = wait(0)) > 0 && w != childPid)
  1672.       ;
  1673.     fprintf(stderr, "done sending mail\n");
  1674.     break;
  1675.     }
  1676.     return;
  1677. }
  1678.  
  1679. /*
  1680.  *----------------------------------------------------------------------
  1681.  *
  1682.  * fatal --
  1683.  *
  1684.  *    Print an error message and terminate the program.
  1685.  *
  1686.  * Results:
  1687.  *    None.
  1688.  *
  1689.  * Side effects:
  1690.  *      A formated error message is printed to stderr, and
  1691.  *      the program is terminated.
  1692.  *
  1693.  *----------------------------------------------------------------------
  1694.  */
  1695.  
  1696. #ifndef lint
  1697. static void
  1698. fatal(va_alist)
  1699.     va_dcl
  1700. {
  1701.     char *errmsg;
  1702.     va_list args;
  1703.     char mailBuf[0x1000];
  1704.     char    *fmt;
  1705.  
  1706.     errmsg = strerror(errno);
  1707.     va_start(args);
  1708.     fmt = va_arg(args, char *);
  1709.     (void) fprintf(stderr, "Dump: ");
  1710.     (void) vfprintf(stderr, fmt, args);
  1711.     (void) fprintf(stderr, ": %s\n", errmsg);
  1712.     (void) fflush(stderr);
  1713.  
  1714.     (void) vsprintf(mailBuf, fmt, args);
  1715.     (void) strcat(mailBuf, ": ");
  1716.     (void) strcat(mailBuf, errmsg);
  1717.     sendMail(mailBuf);
  1718.  
  1719.     va_end(args);
  1720.     exit(1);
  1721. }
  1722. #else
  1723. /*VARARGS1*/
  1724. /*ARGSUSED*/
  1725. void
  1726. fatal(fmt)
  1727.     char *fmt;
  1728. {
  1729.     return;
  1730. }
  1731. #endif  /* !lint */
  1732.  
  1733.  
  1734. /*
  1735.  *----------------------------------------------------------------------
  1736.  *
  1737.  * warning --
  1738.  *
  1739.  *    Print a warning message.
  1740.  *
  1741.  * Results:
  1742.  *    None.
  1743.  *
  1744.  * Side effects:
  1745.  *      A formated error message is printed to stderr.
  1746.  *
  1747.  *----------------------------------------------------------------------
  1748.  */
  1749.  
  1750. #ifndef lint
  1751. static void
  1752. warning(va_alist)
  1753.     va_dcl
  1754. {
  1755.     const char *errmsg;
  1756.     va_list args;
  1757.     char    *fmt;
  1758.  
  1759.     errmsg = strerror(errno);
  1760.     va_start(args);
  1761.     fmt = va_arg(args, char *);
  1762.     (void) fprintf(stderr, "Dump: ");
  1763.     (void) vfprintf(stderr, fmt, args);
  1764.     (void) fprintf(stderr, ": %s\n", errmsg);
  1765.     (void) fflush(stderr);
  1766.     va_end(args);
  1767.     return;
  1768. }
  1769. #else
  1770. /*VARARGS1*/
  1771. /*ARGSUSED*/
  1772. void
  1773. warning(fmt)
  1774.     char *fmt;
  1775. {
  1776.     return;
  1777. }
  1778. #endif  /* !lint */
  1779.  
  1780.  
  1781. /*
  1782.  *----------------------------------------------------------------------
  1783.  *
  1784.  * openLog --
  1785.  *
  1786.  *    Open the dump log file and tee stderr so that all
  1787.  *      error messages are appended to the log.
  1788.  *
  1789.  * Results:
  1790.  *    None.
  1791.  *
  1792.  * Side effects:
  1793.  *      The log file is opened, and stderr is redirected to it.
  1794.  *
  1795.  *----------------------------------------------------------------------
  1796.  */
  1797.  
  1798. static void
  1799. openLog()
  1800. {
  1801.     int pfd[2];
  1802.     char buf[BUFSIZ];
  1803.     int fd;
  1804.  
  1805.     pipe(pfd);
  1806.     switch (fork()) {
  1807.  
  1808.     case -1:
  1809.     fatal("fork failed");
  1810.     /* NOTREACHED */
  1811.  
  1812.     case 0:     /* child */
  1813.         close(pfd[1]);
  1814.     if ((fd = open(LOGFILE, O_APPEND | O_WRONLY | O_CREAT, 0666)) < 0) {
  1815.         warning("Can't open log file %s", LOGFILE);
  1816.         return;
  1817.     }
  1818.     for (;;) {
  1819.         int r;
  1820.  
  1821.         switch (r = read(pfd[0], buf, sizeof(buf))) {
  1822.  
  1823.         case -1:
  1824.         fatal("Error reading from pipe");
  1825.         /* NOTREACHED */
  1826.  
  1827.         case 0:
  1828.         close(fd);
  1829.         exit(0);
  1830.  
  1831.         default:
  1832.         write(2, buf, r);
  1833.         if (write(fd, buf, r) != r) {
  1834.             warning("Error writing to %s", LOGFILE);
  1835.         }
  1836.         continue;
  1837.         }
  1838.     }
  1839.     /* NOTREACHED */
  1840.  
  1841.     default:    /* parent */
  1842.         close(pfd[0]);
  1843.     dup2(pfd[1], 2);        /* write all errors to log */
  1844.     break;
  1845.     }
  1846.     return;
  1847. }
  1848.  
  1849.  
  1850. /*
  1851.  *----------------------------------------------------------------------
  1852.  *
  1853.  * quote_string --
  1854.  *
  1855.  *    Expand all control characters in a string to the equivalent
  1856.  *      backslashed excape sequence.  For instance, a tab is converted
  1857.  *      to the two characters '\' and 't'.
  1858.  *
  1859.  * Results:
  1860.  *    None.
  1861.  *
  1862.  * Side effects:
  1863.  *    Modified the destination string.
  1864.  *
  1865.  *----------------------------------------------------------------------
  1866.  */
  1867.  
  1868. static void
  1869. quote_string(to, from)
  1870.     char *to;
  1871.     const char *from;
  1872. {
  1873.     int c;
  1874.  
  1875.     for (;;) {
  1876.     switch (c = *from++) {
  1877.  
  1878.     case '\0':
  1879.         *to = '\0';
  1880.         return;
  1881.  
  1882.     case '\\':
  1883.         *to++ = '\\';
  1884.         *to++ = '\\';
  1885.         break;
  1886.  
  1887.     case '\n':
  1888.         *to++ = '\\';
  1889.         *to++ = 'n';
  1890.         break;
  1891.  
  1892.     case '\t':
  1893.         *to++= '\\';
  1894.         *to++= 't';
  1895.         break;
  1896.  
  1897.     case '\f':
  1898.         *to++= '\\';
  1899.         *to++= 'f';
  1900.         break;
  1901.  
  1902.     case '\b':
  1903.         *to++= '\\';
  1904.         *to++= 'b';
  1905.         break;
  1906.  
  1907.     default:
  1908.         if (c < 0x20) {
  1909.         *to++ = '\\';
  1910.         *to++ = '0' + ((c >> 3) & 7);
  1911.         *to++ = '0' + (c & 7);
  1912.         break;
  1913.         } else {
  1914.         *to++ = c;
  1915.         }
  1916.     }
  1917.     }
  1918. }
  1919.  
  1920. /*
  1921.  *----------------------------------------------------------------------
  1922.  *
  1923.  * checkTape --
  1924.  *
  1925.  *    Check the dumpdates file to make sure it is safe to initialize
  1926.  *    the tape.  We do this by grepping through the last 100 lines
  1927.  *    of the dumpdates file to see if the tape has been used.
  1928.  *
  1929.  * Results:
  1930.  *    None.
  1931.  *
  1932.  * Side effects:
  1933.  *    Will exit with failure if it is not safe.
  1934.  *
  1935.  *----------------------------------------------------------------------
  1936.  */
  1937.  
  1938. static void
  1939. checkTape()
  1940. {
  1941.     char buf[1000];
  1942.     int status;
  1943.  
  1944.     sprintf(buf,"tail -100 %s | grep \"^%3.3d\" > /dev/null", DUMPDATES,
  1945.         tapeNumber);
  1946.     status = system(buf);
  1947.     if (status==0) {
  1948.     fprintf(stderr,"dump: tape %d recently used; init failed\n",
  1949.         tapeNumber);
  1950.     } else if (status==256 || status==1) {
  1951.     return;
  1952.     } else {
  1953.     fprintf(stderr,"dump: unable to do dumpdates safety check\n");
  1954.     }
  1955.     exit(123);
  1956. }
  1957.  
  1958. /*
  1959.  *----------------------------------------------------------------------
  1960.  *
  1961.  * gotoEOD --
  1962.  *
  1963.  *    Move tape to end-of-data.    
  1964.  *
  1965.  * Results:
  1966.  *    None.
  1967.  *
  1968.  * Side effects:
  1969.  *    The tape is moved.
  1970.  *
  1971.  *----------------------------------------------------------------------
  1972.  */
  1973.  
  1974. static void
  1975. gotoEOD()
  1976. {
  1977.     Dev_TapeCommand     args;
  1978.     ReturnStatus    status;
  1979.     int            files;
  1980.  
  1981.  
  1982.     debugp((stderr, "skipping to end of data\n"));
  1983.     args.command = IOC_TAPE_SKIP_EOD;
  1984.     args.count = 0;
  1985.     status = Fs_IOControl(archivefd, IOC_TAPE_COMMAND, sizeof(args),
  1986.     (char *) &args, 0, NULL);
  1987.     if (status != SUCCESS) {
  1988.     warning("Skip to end of data returned 0x%x", status);
  1989.     /*
  1990.      * If we are doing a restore then we want to do our best to
  1991.      * find the end of usable data. Otherwise we return an error.
  1992.      */
  1993.     fprintf(stderr, "Trying to find last file on tape\n");
  1994.     files = 0;
  1995.     rewindTape();
  1996.     /*
  1997.      * Skip over initial label.
  1998.      */
  1999.     status = skipFiles(1);
  2000.     if (status == SUCCESS) {
  2001.         files++;
  2002.         /*
  2003.          * Now skip over pairs of dump files and labels. 
  2004.          */
  2005.         while(1) {
  2006.         status = skipFiles(2);
  2007.         if (status != SUCCESS) {
  2008.             break;
  2009.         }
  2010.         files += 2;
  2011.         }
  2012.     }
  2013.     fprintf(stderr, "Tape ends with file %d\n", files);
  2014.     rewindTape();
  2015.     status = skipFiles(files);
  2016.     if (status != SUCCESS) {
  2017.         fatal("Can't find end of tape");
  2018.     }
  2019.     }
  2020. }
  2021.  
  2022. /*
  2023.  *----------------------------------------------------------------------
  2024.  *
  2025.  * skipFiles --
  2026.  *
  2027.  *    Skip the given number of files.
  2028.  *
  2029.  * Results:
  2030.  *    Return status from the ioctl.
  2031.  *
  2032.  * Side effects:
  2033.  *    The tape is moved around.
  2034.  *
  2035.  *----------------------------------------------------------------------
  2036.  */
  2037.  
  2038. static ReturnStatus
  2039. skipFiles(num)
  2040.     int        num;    /* Number of files to skip. */
  2041. {
  2042.     ReturnStatus    status;
  2043.     Dev_TapeCommand     args;
  2044.  
  2045.     debugp((stderr, "skipping %d files\n", num));
  2046.     args.command = IOC_TAPE_SKIP_FILES;
  2047.     args.count = num;
  2048.     status = Fs_IOControl(archivefd, IOC_TAPE_COMMAND, sizeof(args),
  2049.               (char *) &args, 0, (char *) 0);
  2050.     return status;
  2051. }
  2052. @
  2053.  
  2054.  
  2055. 1.11
  2056. log
  2057. @Change files from /sprite/admin/dump/foo.new to /sprite/admin/dump/foo.
  2058. (Mike checking in for John.)
  2059. @
  2060. text
  2061. @d18 1
  2062. a18 1
  2063. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.10 91/11/22 15:02:14 jhh Exp Locker: jhh $";
  2064. d112 1
  2065. d114 1
  2066. d165 1
  2067. d167 1
  2068. d199 1
  2069. d201 1
  2070. d321 1
  2071. a321 1
  2072. #else
  2073. d333 1
  2074. a333 1
  2075. #endif    
  2076. d443 1
  2077. a443 1
  2078.     FILE         *fp;
  2079. d926 1
  2080. a926 1
  2081.         strcat(tarargs, "ncfTP");
  2082. d930 1
  2083. a930 1
  2084.         strcat(tarargs, "ncbfTP");
  2085. d1399 1
  2086. d1419 1
  2087. d1426 1
  2088. d1428 1
  2089. a1900 3
  2090.     Dev_TapeStatus    tapeStatus;
  2091.     int            remaining;
  2092.     int            position;
  2093. @
  2094.  
  2095.  
  2096. 1.10
  2097. log
  2098. @if eod can't be found then rewind the tape, and skip over files until
  2099. it fails, then rewind the tape again and skip to the last good file.
  2100. This is the right thing to do for restore, and if the dumps died,
  2101. and if there is a media error
  2102. @
  2103. text
  2104. @d18 1
  2105. a18 1
  2106. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.9 91/11/22 14:09:03 jhh Exp Locker: jhh $";
  2107. d60 3
  2108. a62 3
  2109. #define DUMPDATES                  "/sprite/admin/dump/dumpdates.new"
  2110. #define LOGFILE                 "/sprite/admin/dump/dumplog.new"
  2111. #define DRIVELOG        "/sprite/admin/dump/statuslog.new"
  2112. @
  2113.  
  2114.  
  2115. 1.9
  2116. log
  2117. @added -T option
  2118. @
  2119. text
  2120. @d18 1
  2121. a18 1
  2122. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.8 91/10/11 11:57:18 jhh Exp Locker: jhh $";
  2123. d1894 1
  2124. a1902 1
  2125. #ifdef PROG_RESTORE
  2126. d1908 19
  2127. a1926 5
  2128.     fprintf(stderr, "Trying to skip to just before error\n");
  2129.     status = Fs_IOControl(archivefd, IOC_TAPE_STATUS, 0, NULL, 
  2130.         sizeof(tapeStatus), &tapeStatus);
  2131.     if (status != SUCCESS) {
  2132.         fatal("Can't find the end of data");
  2133. d1928 1
  2134. a1928 2
  2135.     remaining = tapeStatus.remaining;
  2136.     debugp((stderr, "remaining = %d\n", remaining));
  2137. d1930 1
  2138. a1930 2
  2139.     status = Fs_IOControl(archivefd, IOC_TAPE_STATUS, 0, NULL, 
  2140.         sizeof(tapeStatus), &tapeStatus);
  2141. d1932 1
  2142. a1932 1
  2143.         fatal("Can't find the end of data");
  2144. a1933 15
  2145.     debugp((stderr, "remaining = %d\n", tapeStatus.remaining));
  2146.     position = tapeStatus.remaining - remaining - 50000;
  2147.     debugp((stderr, "block = %d\n", position));
  2148.     if (position > 0) {
  2149.         args.command = IOC_TAPE_GOTO_BLOCK;
  2150.         args.count = position;
  2151.         status = Fs_IOControl(archivefd, IOC_TAPE_COMMAND, sizeof(args),
  2152.         (char *) &args, 0, NULL);
  2153.         if (status != SUCCESS) {
  2154.         fatal("Can't skip to block %d", position);
  2155.         }
  2156.     }
  2157. #else
  2158.     fatal("Skip to end of data returned 0x%x", status);
  2159. #endif
  2160. @
  2161.  
  2162.  
  2163. 1.8
  2164. log
  2165. @added -u option, findLastFile
  2166. @
  2167. text
  2168. @d18 1
  2169. a18 1
  2170. static char rcsid[] = "$Header: /sprite/src/admin/dump.new/RCS/main.c,v 1.7 91/09/10 11:16:59 jhh Exp $";
  2171. d112 1
  2172. d141 1
  2173. d951 5
  2174. d957 1
  2175. a957 1
  2176.         strcpy(tarargs, "xpf");
  2177. d959 1
  2178. a959 1
  2179.         strcpy(tarargs, "xpfb");
  2180. @
  2181.  
  2182.  
  2183. 1.7
  2184. log
  2185. @added new dump format
  2186. @
  2187. text
  2188. @d18 1
  2189. a18 1
  2190. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.5 91/06/05 15:06:58 mgbaker Exp Locker: shirriff $";
  2191. d101 2
  2192. a102 2
  2193. static int reInitialize;
  2194. static int reInitializeSafe;
  2195. d111 1
  2196. d127 1
  2197. d161 1
  2198. d194 2
  2199. d203 9
  2200. a235 1
  2201.     startTime = time(0L);
  2202. d317 2
  2203. d450 4
  2204. a453 2
  2205.     if ((fp = fopen(DUMPDATES, "a")) == NULL) {
  2206.     fatal("Can't open %s", DUMPDATES);
  2207. d481 1
  2208. a481 1
  2209.     (void) sprintf(buf, "%03d %02d %d %6.1lf %6.1lf %s  %s\n",
  2210. d484 11
  2211. a494 2
  2212.     fprintf(fp, "%s", buf);
  2213.     (void) fclose(fp);
  2214. a528 4
  2215.     if (archiveFileIsATapeDrive) {
  2216.     strcat(tapeBuffer, buf);
  2217.     writeTapeLabel();
  2218.     }
  2219. d1286 21
  2220. a1306 2
  2221.     if ((fp = fopen(DUMPDATES, "a")) == NULL) {
  2222.     fatal("Can't open %s", DUMPDATES);
  2223. a1307 5
  2224.     /*
  2225.      *   Put a comment in the dump data file.
  2226.      */
  2227.     fprintf(fp, "# Initializing tape number %03d\n", tapeNumber);
  2228.     (void) fclose(fp);
  2229. d1387 20
  2230. d1880 1
  2231. a1880 1
  2232. gotoEOD(VOID)
  2233. d1884 3
  2234. d1888 1
  2235. d1895 35
  2236. a1929 1
  2237.     fatal("Can't skip to end of data");
  2238. @
  2239.  
  2240.  
  2241. 1.6
  2242. log
  2243. @Added checkTape function to ensure a recent tape doesn't get
  2244. accidentally initialized.
  2245. @
  2246. text
  2247. @d39 2
  2248. a40 3
  2249. #ifdef __STDC__
  2250. #include <stdarg.h>
  2251. #else
  2252. a41 1
  2253. #endif
  2254. d43 3
  2255. d47 1
  2256. a47 2
  2257. extern int errno;
  2258. extern int open();
  2259. d49 1
  2260. d51 3
  2261. a53 4
  2262.  
  2263. #define SPRITE_DUMP_HEADER     "SPRITE DUMP TAPE #"
  2264. #define DUMPDATES              "/sprite/admin/dump/dumpdates"
  2265. #define LOGFILE             "/sprite/admin/dump/dumplog"
  2266. d55 9
  2267. a63 1
  2268. #define TAR               "tar.gnu"
  2269. d67 1
  2270. a68 2
  2271. #define TOC_SIZE     MBytes(10)    /* TOC occupied 10 MB on the tape */
  2272. #define    TOC_USEABLE    MBytes(2)    /* About 2 MB of it can be used */
  2273. d70 11
  2274. d86 1
  2275. a86 1
  2276. static int dumpLevel;
  2277. d88 1
  2278. a90 1
  2279. static long startTime;
  2280. d105 6
  2281. d141 36
  2282. a176 30
  2283. static void cleanup_sighup(void);
  2284. static void cleanup_sigint(void);
  2285. static void cleanup_sigquit(void);
  2286. static void cleanup_sigpipe(void);
  2287. static void cleanup_sigterm(void);
  2288.  
  2289. static void openArchiveFile(void);
  2290. static void forkOffTar(void);
  2291. static void dumpDirectory(const char *dir);
  2292. static void initializeTape(void);
  2293. static void sendMail(const char *msg);
  2294. static void rewindTape(void);
  2295. static void fatal(const char *fmt, ...);
  2296. static void warning(const char *fmt, ...);
  2297. static void readTapeLabel(void);
  2298. static void rewindTape(void);
  2299. static void openLog(void);
  2300. static void skipOverFiles(void);
  2301. static void waitForChildToDie(void);
  2302. static void setFileNumber(void);
  2303. static void quote_string(char *to, const char *from);
  2304. static void checkTape(void);
  2305. static int parseDumpInfo(char *buf);
  2306.  
  2307. #ifdef PROG_DUMP
  2308. static int  getNextDumpDateEntry(void);
  2309. static void writeTapeLabel(void);
  2310. static void flushOutput(void);
  2311. static void getDumpDate(void);
  2312. static void recordTime(void);
  2313. d190 1
  2314. d198 1
  2315. a198 1
  2316.     argc = Opt_Parse(argc, argv, OptionArray, Opt_Number(OptionArray));
  2317. d217 5
  2318. d227 1
  2319. a237 1
  2320.     rewindTape();
  2321. d269 12
  2322. a280 1
  2323.     skipOverFiles();
  2324. d298 2
  2325. d309 1
  2326. a310 3
  2327.     rewindTape();
  2328.     debugp((stderr, "finished dumping %s, %ld bytes\n",
  2329.         directoryToDump, totalBytes));
  2330. d338 1
  2331. a338 1
  2332.     const char *dir;
  2333. d391 3
  2334. a393 1
  2335.     int     nbytes;
  2336. d420 14
  2337. a433 3
  2338.     FILE *fp;
  2339.     char buf[0x1000];
  2340.     char *date;
  2341. d440 27
  2342. a466 3
  2343.     (void) sprintf(buf, "%03d %02d %d %10d  %s  %s\n",
  2344.            tapeNumber, fileNumber, dumpLevel, totalBytes,
  2345.            date, directoryToDump);
  2346. d469 34
  2347. d573 1
  2348. a573 1
  2349.     static char const months[][4] = {
  2350. d580 2
  2351. d583 1
  2352. d588 1
  2353. a588 2
  2354.     debugp((stderr, "parseDumpInfo:  mismatch on first token\n"));
  2355.     return 0;
  2356. d591 1
  2357. a591 1
  2358.  
  2359. d596 1
  2360. a596 2
  2361.     debugp((stderr, "parseDumpInfo:  mismatch on second token\n"));
  2362.     return 0;
  2363. d599 1
  2364. d607 1
  2365. a607 2
  2366.     debugp((stderr, "parseDumpInfo:  mismatch on third token\n"));
  2367.     return 0;
  2368. d610 1
  2369. d614 20
  2370. a633 2
  2371.     dumpDateEntry.nbytes = atoi(s);
  2372.  
  2373. d641 1
  2374. a641 2
  2375.     debugp((stderr, "parseDumpInfo:  mismatch on fifth token\n"));
  2376.     return 0;
  2377. d643 1
  2378. d645 1
  2379. a645 2
  2380.     debugp((stderr, "parseDumpInfo:  mismatch on sixth token\n"));
  2381.     return 0;
  2382. d647 1
  2383. d654 1
  2384. a654 2
  2385.     debugp((stderr, "parseDumpInfo:  mismatch on month\n"));
  2386.     return 0;
  2387. d657 1
  2388. a657 2
  2389.     debugp((stderr, "parseDumpInfo:  mismatch on date\n"));
  2390.     return 0;
  2391. d659 1
  2392. d662 1
  2393. a662 2
  2394.     debugp((stderr, "parseDumpInfo:  mismatch on hour\n"));
  2395.     return 0;
  2396. d664 1
  2397. d667 1
  2398. a667 2
  2399.     debugp((stderr, "parseDumpInfo:  mismatch on minute\n"));
  2400.     return 0;
  2401. d669 1
  2402. d672 1
  2403. a672 2
  2404.     debugp((stderr, "parseDumpInfo:  mismatch on seconds\n"));
  2405.     return 0;
  2406. d674 1
  2407. d677 1
  2408. a677 2
  2409.     debugp((stderr, "parseDumpInfo:  mismatch on year\n"));
  2410.     return 0;
  2411. d686 1
  2412. d688 1
  2413. a688 2
  2414.     debugp((stderr, "parseDumpInfo:  mismatch on last token\n"));
  2415.     return 0;
  2416. d696 5
  2417. d763 2
  2418. d797 22
  2419. d847 20
  2420. a866 2
  2421.     char tarargs[20];
  2422.     
  2423. d895 10
  2424. a904 3
  2425.     strcat(tarargs, "ncfTP");
  2426.     debugp((stderr, "execing tar %s - -\n", tarargs));
  2427.     execlp(TAR, TAR, tarargs, "-", "-", NULL);
  2428. a913 2
  2429.     char **arg;
  2430.     int i;
  2431. d915 1
  2432. d922 10
  2433. a931 4
  2434.     case 0:
  2435.     arg = (char **) malloc(sizeof(char **) * (progArgc + 4));
  2436.     arg[0] = TAR;
  2437.     strcpy(tarargs, "xpf");
  2438. d941 6
  2439. a946 3
  2440.     arg[1] = tarargs;
  2441.     arg[2] = archiveFileName;
  2442.     for (i = 1; (arg[2 + i] = progArgv[i]) != NULL; ++i) {
  2443. d949 5
  2444. d956 1
  2445. a956 1
  2446.  
  2447. d1052 4
  2448. d1058 30
  2449. a1087 3
  2450.     rewindTape();
  2451.     if (read(archivefd, tapeBuffer, sizeof(tapeBuffer)) != sizeof(tapeBuffer)) {
  2452.     fatal("Error reading tape label");
  2453. d1089 71
  2454. a1159 3
  2455.     if (strncmp(tapeBuffer,
  2456.         SPRITE_DUMP_HEADER, strlen(SPRITE_DUMP_HEADER)) != 0) {
  2457.     fatal("The tape does not have a correct label");
  2458. d1161 3
  2459. a1163 2
  2460.     tapeNumber= atoi(tapeBuffer + strlen(SPRITE_DUMP_HEADER));
  2461.     debugp((stderr, "Using tape #%d\n", tapeNumber));
  2462. d1172 1
  2463. a1172 1
  2464.  * readTapeLabel --
  2465. d1190 6
  2466. a1195 3
  2467.     rewindTape();
  2468.     if (write(archivefd, tapeBuffer,
  2469.           sizeof(tapeBuffer)) != sizeof(tapeBuffer)) {
  2470. d1198 7
  2471. a1204 1
  2472.     rewindTape();
  2473. d1214 4
  2474. d1224 23
  2475. a1246 4
  2476.     memset(tapeBuffer, '\0', sizeof(tapeBuffer));
  2477.     sprintf(tapeBuffer, "%s%d\n", SPRITE_DUMP_HEADER, tapeNumber);
  2478.     if (write(archivefd, tapeBuffer,
  2479.           sizeof(tapeBuffer)) != sizeof(tapeBuffer)) {
  2480. d1249 11
  2481. a1259 4
  2482.     memset(tapeBuffer, '\0', sizeof(tapeBuffer));
  2483.     for (nbufs = TOC_SIZE / IOBUF_SIZE; --nbufs > 0;) {
  2484.     if (write(archivefd, tapeBuffer,
  2485.           sizeof(tapeBuffer)) != sizeof(tapeBuffer)) {
  2486. d1263 1
  2487. d1324 2
  2488. a1325 1
  2489.     if (strlen(dumpDateEntry.dirname) > len) {
  2490. d1353 3
  2491. a1355 2
  2492.     Dev_TapeCommand args;
  2493.     int status;
  2494. a1356 1
  2495.     debugp((stderr, "skipping %d files\n", fileNumber));
  2496. d1358 11
  2497. a1368 5
  2498.     rewindTape();
  2499.     args.command = IOC_TAPE_SKIP_FILES;
  2500.     args.count = fileNumber;
  2501.     status = Fs_IOControl(archivefd, IOC_TAPE_COMMAND, sizeof(args),
  2502.               (char *) &args, 0, (char *) 0);
  2503. d1373 7
  2504. a1379 4
  2505.     debugp((stderr, "Backing up one file\n"));
  2506.     args.count = -1;
  2507.     status = Fs_IOControl(archivefd, IOC_TAPE_COMMAND, sizeof(args),
  2508.               (char *) &args, 0, (char *) 0);
  2509. d1385 12
  2510. d1402 1
  2511. d1404 2
  2512. a1405 1
  2513. cleanup_sighup(void)
  2514. d1412 1
  2515. d1414 2
  2516. a1415 1
  2517. cleanup_sigint(void)
  2518. d1422 1
  2519. d1424 2
  2520. a1425 1
  2521. cleanup_sigquit(void)
  2522. d1432 1
  2523. d1434 2
  2524. a1435 1
  2525. cleanup_sigpipe(void)
  2526. d1460 1
  2527. d1462 2
  2528. a1463 1
  2529. cleanup_sigterm(void)
  2530. a1545 1
  2531. #ifdef __STDC__
  2532. d1547 1
  2533. a1547 4
  2534. fatal(const char *fmt, ...)
  2535. #else
  2536. void
  2537. fatal(fmt, va_alist)
  2538. a1548 1
  2539. #endif
  2540. d1550 1
  2541. a1550 1
  2542.     const char *errmsg;
  2543. d1553 1
  2544. a1555 3
  2545. #ifdef __STDC__
  2546.     va_start(args, fmt);
  2547. #else
  2548. d1557 1
  2549. a1557 1
  2550. #endif
  2551. d1600 2
  2552. a1601 6
  2553. #ifdef __STDC__
  2554. void
  2555. warning(const char *fmt, ...)
  2556. #else
  2557. void
  2558. warning(fmt, va_alist)
  2559. a1602 1
  2560. #endif
  2561. d1606 1
  2562. a1608 3
  2563. #ifdef __STDC__
  2564.     va_start(args, fmt);
  2565. #else
  2566. d1610 1
  2567. a1610 1
  2568. #endif
  2569. d1805 63
  2570. @
  2571.  
  2572.  
  2573. 1.5
  2574. log
  2575. @Made dump program operate under userid "dumper", so dump effects
  2576. can be removed from traces of system performance.
  2577. (checked in by shirriff)
  2578. @
  2579. text
  2580. @d18 1
  2581. a18 1
  2582. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.4 91/05/10 17:00:37 mgbaker Exp Locker: mgbaker $";
  2583. d84 1
  2584. d99 1
  2585. d138 1
  2586. d203 4
  2587. a206 1
  2588.     if (reInitialize) {
  2589. d1408 37
  2590. @
  2591.  
  2592.  
  2593. 1.4
  2594. log
  2595. @Mary checking this in for Bob.
  2596. @
  2597. text
  2598. @d18 1
  2599. a18 1
  2600. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.3 90/11/15 01:21:03 rab Exp Locker: rab $";
  2601. d29 1
  2602. d151 6
  2603. d158 1
  2604. d167 16
  2605. @
  2606.  
  2607.  
  2608. 1.3
  2609. log
  2610. @Improved error messages.
  2611. @
  2612. text
  2613. @d18 1
  2614. a18 1
  2615. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.2 90/10/07 15:10:39 rab Exp Locker: rab $";
  2616. d229 1
  2617. d231 1
  2618. @
  2619.  
  2620.  
  2621. 1.2
  2622. log
  2623. @Fixed to handle backslash in filename.  Also some other bug fixes.
  2624. @
  2625. text
  2626. @d18 1
  2627. a18 1
  2628. static char rcsid[] = "$Header: /sprite/src/admin/dump/RCS/main.c,v 1.1 90/09/07 11:47:34 rab Exp Locker: rab $";
  2629. d51 2
  2630. a52 2
  2631. #define DUMPDATES              "/sprite/admin/dump/new-dumpdates"
  2632. #define LOGFILE             "/sprite/admin/dump/new-dumplog"
  2633. d76 2
  2634. a77 1
  2635. static int errors;
  2636. a81 1
  2637. static int relativePaths;
  2638. d91 1
  2639. a91 1
  2640.   { OPT_TRUE,   "d", (char *) &debug,            "Debug"                   },
  2641. d103 1
  2642. d106 1
  2643. a106 1
  2644.   { OPT_TRUE,   "d", (char *) &debug,            "Debug"                   },
  2645. a122 1
  2646. static int  getNextDumpDateEntry(void);
  2647. a128 1
  2648. static void writeTapeLabel(void);
  2649. d134 1
  2650. a135 1
  2651. static void quote_string(char *to, const char *from);
  2652. d138 2
  2653. d211 2
  2654. a212 2
  2655.     if (errors) {
  2656.     sendMail("Dump completed with non-fatal errors.");
  2657. d214 5
  2658. a218 1
  2659.     sendMail("Dump completed successfully.");
  2660. d232 4
  2661. a235 2
  2662.     debugp((stderr, "%s exiting, there were %d errors\n", argv[0], errors));
  2663.     exit(errors);
  2664. d269 1
  2665. a269 1
  2666.     ++errors;
  2667. d285 1
  2668. a285 1
  2669.         ++errors;
  2670. d292 1
  2671. a292 1
  2672.         ++errors;
  2673. d308 10
  2674. a359 9
  2675. static struct {
  2676.     int     tape;
  2677.     int     file;
  2678.     int     level;
  2679.     int     nbytes;
  2680.     time_t  time;
  2681.     char    dirname[MAXPATHLEN];
  2682. } dumpDateEntry;
  2683.  
  2684. d416 1
  2685. a416 1
  2686.  
  2687. d530 2
  2688. d566 1
  2689. d730 1
  2690. d757 1
  2691. d768 25
  2692. a792 3
  2693.     if (ws.w_retcode) {
  2694.     warning("tar exited with nozero status: %d", ws.w_retcode);
  2695.     ++errors;
  2696. d833 1
  2697. d863 1
  2698. d1045 1
  2699. a1045 1
  2700.     ++errors;
  2701. @
  2702.  
  2703.  
  2704. 1.1
  2705. log
  2706. @Initial revision
  2707. @
  2708. text
  2709. @d18 1
  2710. a18 1
  2711. static char rcsid[] = "$Header$";
  2712. d84 1
  2713. a85 1
  2714.  
  2715. d91 1
  2716. d105 1
  2717. d136 1
  2718. d255 1
  2719. d281 1
  2720. d283 1
  2721. a283 1
  2722.         if (puts(pathname) == EOF) {
  2723. d287 1
  2724. a287 1
  2725.         fprintf(stderr, "%s\n", pathname);
  2726. d392 5
  2727. a396 1
  2728.     if (((s = strtok(buf, " \t\n")) == NULL) || *s == '\0' || *s == '#') {
  2729. d400 2
  2730. a401 2
  2731.         fatal("format error in %s: line %d, char %d",
  2732.         DUMPDATES, lineCnt, s - buf);
  2733. d427 1
  2734. d436 1
  2735. d447 1
  2736. d463 1
  2737. d467 1
  2738. d476 1
  2739. d480 1
  2740. d485 1
  2741. d490 1
  2742. d495 1
  2743. d500 1
  2744. d506 1
  2745. d511 1
  2746. d615 2
  2747. a616 1
  2748.     fatal("%s: not a normal file or tape drive", archiveFileName);
  2749. d663 6
  2750. d700 3
  2751. d881 1
  2752. a881 2
  2753.     char *s, *end;
  2754.  
  2755. d890 1
  2756. d902 1
  2757. a902 1
  2758.     for (; *s != '\0'; ++n) {
  2759. d913 2
  2760. a914 2
  2761.         if (strncmp(dumpDateEntry.dirname,
  2762.                 progArgv[1], strlen(dumpDateEntry.dirname)) == 0) {
  2763. d918 9
  2764. d995 18
  2765. d1267 72
  2766. @
  2767.